package com.gs.core.service.impl;

import java.util.Date;
import java.util.List;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.transaction.support.TransactionTemplate;

import com.gs.core.domain.Person;
import com.gs.core.domain.SaveEntityAction;
import com.gs.core.repository.ActionRepository;
import com.gs.core.repository.PersonRepository;
import com.gs.core.service.PersonService;
import com.gs.core.service.dao.PersonDAO;

@Service(value="personService")
public class PersonServiceImpl implements PersonService {

	@Autowired
	PersonRepository personRepository;
	
	@Autowired
	ActionRepository actionRepository;
	
	@Autowired
	@Qualifier(value="personDAO")
	PersonDAO personDAO;
	
	private TransactionTemplate transactionTemplate;
	
	@Autowired
	public void setTransactionTemplate(PlatformTransactionManager platformTransactionManager) {
		this.transactionTemplate = new TransactionTemplate(platformTransactionManager);
	}
	
	
	public List<Person> findAll() {
		return personRepository.findAll();
	}

	public Person findById(Long id) {
		return personRepository.findOne(id);
	}
	
	@Override
	public Person saveOrUpdateWithTransactionTemplate(final Person entity){
		System.out.println("saveOrUpdateWithTransactionTemplate() : TransactionSynchronizationManager.isActualTransactionActive() ? " + TransactionSynchronizationManager.isActualTransactionActive());
		return transactionTemplate.execute(new TransactionCallback<Person>() {

			@Override
			public Person doInTransaction(TransactionStatus status) {
				Person savedPerson = null;
				try {
					savedPerson = saveOrUpdate(entity);
				} catch (Exception e) {
					System.out.println("Setting rollbackOnly");
					status.setRollbackOnly();
				}
				return savedPerson;
			}
		});
//		return saveOrUpdate(entity);
	}
	
	public Person saveOrUpdate(Person entity) {
		System.out.println("saveOrUpdate() TransactionSynchronizationManager.isActualTransactionActive() ? " + TransactionSynchronizationManager.isActualTransactionActive());
		if(entity.getId()==null){
			SaveEntityAction action = new SaveEntityAction();
			action.setEntityClassName(entity.getClass().getName());
			action.setDescription("Added as a stand alone action. " + entity.getFirstName());
			action.setPerformedAt(new Date());
			action.setActionPerformedBy(entity);
//			actionRepository.save(action);
			entity.add(action);
		}
		
//		if(true){
//			throw new RuntimeException("Force runtime exception..");
//		}
		
		
		return personDAO.save(entity);
//		return personRepository.save(entity);
	}

	public void delete(Person entity) {
		personRepository.delete(entity);
	}

	public void deleteAll() {
		personRepository.deleteAll();
	}

}
